/*
 * Please retain this license and the author marks in your distributions
 * for this and any derived software.
 */
/*
    Licensed to the Apache Software Foundation (ASF) under one
           or more contributor license agreements.  See the NOTICE file
           distributed with this work for additional information
           regarding copyright ownership.  The ASF licenses this file
           to you under the Apache License, Version 2.0 (the
           "License"); you may not use this file except in compliance
           with the License.  You may obtain a copy of the License at

             http://www.apache.org/licenses/LICENSE-2.0

           Unless required by applicable law or agreed to in writing,
           software distributed under the License is distributed on an
           "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
           KIND, either express or implied.  See the License for the
           specific language governing permissions and limitations
           under the License.    

 */
package com.eduyayo.struts2.action;

import java.io.PrintStream;
import java.util.Collection;
import java.util.Iterator;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtils;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.Result;

/**
 * Implements a JSON result type that can be applied to any bean collection and
 * render a list of options.
 * 
 * @author Yayo eduyayo@gmail.com eduardofq@gmail.com
 * 
 */
public class JSONOptionsResultType implements Result {

    /**
     * Default serial version id
     */
    private static final long serialVersionUID = 1L;

    /**
     * Default list name in the value stack.
     */
    private String listName = "options";

    /**
     * Default label property.
     */
    private String labelProperty = "label";

    /**
     * Default value property.
     */
    private String valueProperty = "value";

    /**
     * Tells whether the beans in the list must be rendered as String or via
     * property getters.
     */
    private boolean string = false;

    /**
     * Returns the property that will be invoked to get the label for a single
     * option.
     * 
     * @return
     */
    public String getLabelProperty() {
	return labelProperty;
    }

    /**
     * Changes the property that will be invoked to get the label for a single
     * option.
     * 
     * @return
     */
    public void setLabelProperty(String labelProperty) {
	this.labelProperty = labelProperty;
    }

    /**
     * Returns the property that will be invoked to get the value for a single
     * option.
     * 
     * @return
     */
    public String getValueProperty() {
	return valueProperty;
    }

    /**
     * Returns the property that will be invoked to get the value for a single
     * option.
     * 
     * @return
     */
    public void setValueProperty(String valueProperty) {
	this.valueProperty = valueProperty;
    }

    /**
     * Tells whether the beans in the list must be rendered as String or via
     * property getters.
     * 
     * @return
     */
    public boolean isString() {
	return string;
    }

    /**
     * changes the behaviour for the beans to be rendered as Strings or via
     * property getters.
     * 
     * @return
     */
    public void setString(boolean string) {
	this.string = string;
    }

    /**
     * Renders the list.
     */
    @SuppressWarnings("unchecked")
    @Override
    public void execute(ActionInvocation invocation) throws Exception {
	HttpServletResponse response = (HttpServletResponse) invocation
		.getInvocationContext()
		.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse");
	PrintStream out = new PrintStream(response.getOutputStream());
	StringBuffer buff = new StringBuffer();
	Collection<Object> options = (Collection<Object>) invocation.getStack()
		.findValue(listName);
	buff.append("[\n");
	if (options != null) {
	    for (Iterator<Object> it = options.iterator(); it.hasNext();) {
		Object bean = it.next();
		if (isString()) {
		    buff.append("['").append(bean.toString()).append("', '")
			    .append(bean.toString()).append("']");
		} else {
		    buff.append("['").append(
			    BeanUtils.getProperty(bean, getLabelProperty()))
			    .append("', '").append(
				    BeanUtils.getProperty(bean,
					    getValueProperty())).append("']");
		}
		if (it.hasNext()) {
		    buff.append(",\n");
		} else {
		    buff.append("\n");
		}
	    }
	}
	buff.append("]\n");
	out.println(buff.toString());
    }

    /**
     * Changes the list name to lookup in the value stack.
     * @param listName
     */
    public void setListName(String listName) {
	this.listName = listName;
    }

}
